var _SuperArea = require('scenes/game/gamearea.js');
var _inherit = require('core/inherit.js');
var _global = require('global/global.js');

var _Prefer = require('config/prefer.js');
var _Toturial = require('./toturials.js');
var _Constance = require('scenes/game/constant.js');

// ==========================
// GameArea
// ==========================
function SlotPool() {
    this.mBlock = true;// new cell is generated in current class
    this.mBlockOnFinish = true;
    this.mCells = [];
}
SlotPool.prototype.isBlock = function () {
    return this.mBlock;
};
SlotPool.prototype.hasSlot = function () {
    return this.mCells.length > 0;
};
SlotPool.prototype.nextSlot = function () {
    var s = this.mCells.shift();
    if (this.mCells.length == 0) {
        this.mBlock = this.mBlockOnFinish;
    }
    return s;
};
SlotPool.prototype.setBlocking = function (block) {
    this.mBlock = block;
    this.mBlockOnFinish = block;
};
SlotPool.prototype.addSlots = function (slots, block) {
    this.mCells = this.mCells.concat(slots);
    this.mBlockOnFinish = block;
};
SlotPool.prototype.toString = function () {
    return '[object SlotPool]'
};

// ==========================
// GameArea
// ==========================
function GameArea() {
    _SuperArea.call(this);
    this.mSlotsGen = new SlotPool();

    this.mLocal.add('gamearea', this);
    this.mLocal.add('gamearea.cells', this.mCells);
    this.mLocal.add('gamearea.slotpool', this.mSlotsGen);
    this.mLocal.add(_Constance.RELEASE_ID, [module]);// mark for release

    this.mLayers = [];// temp drawable layers
    this.mToturials = new _Toturial(this);

    _global.scheduleTask(this.startToturial, this);
}
_inherit(GameArea, _SuperArea);
_super = _SuperArea.prototype;

GameArea.prototype.startToturial = function () {
    this.mToturials.nextStep();
};
GameArea.prototype.toturialFinished = function () {
    _Prefer.finishToturial();
    _Prefer.save();

    var tuturialProto = GameArea.prototype;
    for (var i in tuturialProto) {
        if (i != 'constructor' && tuturialProto.hasOwnProperty(i) && _super[i]) {
            this[i] = _super[i];
        }
    }

    // unregist toturial modules
    var modules = this.mLocal.find(_Constance.RELEASE_ID);
    while (modules.length > 0) {
        modules.pop().unregister();
    }
};

// ---------------- over drawables
GameArea.prototype.recoverFromLostContext = function (context) {
    _super.recoverFromLostContext.call(this, context);
    for (var i = 0; i < this.mLayers.length; i++) {
        this.mLayers[i].recoverFromLostContext(context);
    }
};
GameArea.prototype.drawContent = function (context) {
    _super.drawContent.call(this, context);
    for (var i = 0; i < this.mLayers.length; i++) {
        this.mLayers[i].draw(context);
    }
};
GameArea.prototype.addView = function (view) {
    this.mLayers.push(view);
};
GameArea.prototype.removeView = function (view) {
    for (var i = 0; i < this.mLayers.length; i++) {
        if (this.mLayers[i] === view) {
            this.mLayers.splice(i, 1);
            break;
        }
    }
};

// ---------------- overwrite super
GameArea.prototype.startAbsorb = function (direction, vec) {
    if (!this.mSlotsGen.isBlock() || this.mSlotsGen.hasSlot()) {
        _super.startAbsorb.apply(this, arguments);
    } else {
        // slot generate blocked
        var merge = this.mAbsorbs.startAbsorbOnly(direction, vec);
        if (merge) {
            // if merged, update merged history
            this.mCells.predictMerge(this.mPredict);
        }
        this.mAbsorbs.start();
    }
    this.mToturials.onAbsorbStart(this.mAbsorbs.isAbsorbAccepted());
};
GameArea.prototype.onAbsorbFinished = function (hasslide) {
    this.mToturials.onMergeBefore(this.mCells);
    _super.onAbsorbFinished.call(this, hasslide);
    this.mToturials.onMergeFinish(this.mCells);
};

GameArea.prototype.onSlideinStart = function (slot) {
    var gened = this.mSlotsGen.hasSlot();
    var nextcell = gened ? this.mSlotsGen.nextSlot() : this.mNextCell;
    var cell = this.createCell(nextcell);
    slot.bindCell(cell);

    // check if there is possiable movement, prepare for the next slide
    this.mCells.prepareMove();

    if (this.mCells.isNoMove()) {
        this.fire('gameover', this.mCells);
    } else {
        if (!gened) {
            this.prepareNext();
        }
    }

    this.mToturials.onSlideinStart(nextcell);
};
GameArea.prototype.onSlideinFinish = function () {
    _super.onSlideinFinish.call(this);
    this.mToturials.onSlideinFinish();
};

module.exports = GameArea;